home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / tprim_pup.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  19KB  |  792 lines

  1. /*
  2.  * (c) Copyright 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for
  6.  * any purpose and without fee is hereby granted, provided that the above
  7.  * copyright notice appear in all copies and that both the copyright notice
  8.  * and this permission notice appear in supporting documentation, and that
  9.  * the name of Silicon Graphics, Inc. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.
  12.  *
  13.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  14.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  15.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  16.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  17.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  18.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  19.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  20.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  21.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  22.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  23.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  24.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  29.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  30.  * clause at DFARS 252.227-7013 and/or in similar or successor
  31.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  32.  * Unpublished-- rights reserved under the copyright laws of the
  33.  * United States.  Contractor/manufacturer is Silicon Graphics,
  34.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  35.  *
  36.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  37.  */
  38. #include <GL/glx.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <unistd.h>
  42. #include <stdlib.h>
  43. #include <X11/keysym.h>
  44.  
  45. #include "pup.h"
  46.  
  47. static int RGB_attributes[] = {
  48.     GLX_RGBA,
  49.     GLX_RED_SIZE, 1,
  50.     GLX_GREEN_SIZE, 1,
  51.     GLX_BLUE_SIZE, 1,
  52.     None,
  53. };
  54.  
  55. static int CI_attributes[] = {
  56.     None,
  57. };
  58.  
  59. int rgb = 1;
  60.  
  61. #define PIXEL_CENTER(x) ((long) (x) + 0.5)
  62. #define SETCOLOR(x) (rgb ? glColor3fv(rgbMap[x]) : glIndexf(x))
  63.  
  64. enum {
  65.     BLACK = 0,
  66.     RED,
  67.     GREEN,
  68.     YELLOW,
  69.     BLUE,
  70.     MAGENTA,
  71.     CYAN,
  72.     WHITE
  73. };
  74.  
  75. static float rgbMap[8][3] = {
  76.     {0, 0, 0},
  77.     {1, 0, 0},
  78.     {0, 1, 0},
  79.     {1, 1, 0},
  80.     {0, 0, 1},
  81.     {1, 0, 1},
  82.     {0, 1, 1},
  83.     {1, 1, 1}
  84. };
  85.  
  86.  
  87. #define GAP 10
  88. #define ROWS 3
  89. #define COLS 4
  90.  
  91. static long W = COLS*100 + (COLS + 1)*GAP;
  92. static long H = ROWS*100 + (ROWS + 1)*GAP;
  93. static long boxW = 101;
  94. static long boxH = 101;
  95.  
  96. static void Viewport(long row, long column)
  97. {
  98.     long x, y;
  99.  
  100.     x = GAP + column * (boxW + GAP);
  101.     y = GAP + row * (boxH + GAP);
  102.  
  103.     if (rgb) {
  104.     glClearColor(0, 0, 0, 0);
  105.     } else {
  106.     glClearIndex(0);
  107.     }
  108.  
  109.     glEnable(GL_SCISSOR_TEST);
  110.     glScissor(x, y, boxW, boxH);
  111.     glViewport(x, y, boxW, boxH);
  112.  
  113.     glPushAttrib(GL_COLOR_BUFFER_BIT);
  114.     glColorMask(1, 1, 1, 1);
  115.     glIndexMask(~0);
  116.     glClear(GL_COLOR_BUFFER_BIT);
  117.     glPopAttrib();
  118.  
  119.     glMatrixMode(GL_PROJECTION);
  120.     glLoadIdentity();
  121.     glOrtho(-boxW/2, boxW/2, -boxH/2, boxH/2, 0.0, 1.0);
  122.     glMatrixMode(GL_MODELVIEW);
  123. }
  124.  
  125. static void Point(void)
  126. {
  127.     long i;
  128.  
  129.     SETCOLOR(WHITE);
  130.     glBegin(GL_POINTS);
  131.     glVertex2i(0, 0);
  132.     for (i = 1; i < 8; i++) {
  133.         long j = i * 2;
  134.         SETCOLOR(i);
  135.         glVertex2i(-j, -j);
  136.         glVertex2i(-j, 0);
  137.         glVertex2i(-j, j);
  138.         glVertex2i(0, j);
  139.         glVertex2i(j, j);
  140.         glVertex2i(j, 0);
  141.         glVertex2i(j, -j);
  142.         glVertex2i(0, -j);
  143.     }
  144.     glEnd();
  145. }
  146.  
  147. static void Lines(void)
  148. {
  149.     long i;
  150.  
  151.     glPushMatrix();
  152.     glTranslatef(-12, 0, 0);
  153.     for (i = 1; i < 8; i++) {
  154.     SETCOLOR(i);
  155.     glBegin(GL_LINES);
  156.         glVertex2i(-boxW/4, -boxH/4);
  157.         glVertex2i(boxW/4, boxH/4);
  158.     glEnd();
  159.     glTranslatef(4, 0, 0);
  160.     }
  161.     glPopMatrix();
  162.  
  163.     /*
  164.     ** Draw a single vertex line to make sure nothing bad happens
  165.     */
  166.     glBegin(GL_LINES);
  167.     glVertex2i(0, 0);
  168.     glEnd();
  169. }
  170.  
  171. static void LineStrip(void)
  172. {
  173.     glBegin(GL_LINE_STRIP);
  174.     SETCOLOR(RED);
  175.     glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
  176.     SETCOLOR(GREEN);
  177.     glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
  178.     SETCOLOR(BLUE);
  179.     glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
  180.     SETCOLOR(WHITE);
  181.     glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
  182.     glEnd();
  183.  
  184.     /*
  185.     ** Draw a single vertex line to make sure nothing bad happens
  186.     */
  187.     glBegin(GL_LINE_STRIP);
  188.     glVertex2i(0, 0);
  189.     glEnd();
  190. }
  191.  
  192. static void LineLoop(void)
  193. {
  194.     glBegin(GL_LINE_LOOP);
  195.     SETCOLOR(RED);
  196.     glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
  197.     SETCOLOR(GREEN);
  198.     glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
  199.     SETCOLOR(BLUE);
  200.     glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
  201.     SETCOLOR(WHITE);
  202.     glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
  203.     glEnd();
  204.  
  205.     /*
  206.     ** Draw a two vertex line with XOR on to make sure that only the
  207.     ** endpoints show.  Since each line segment is drawn half-open,
  208.     ** the endpoints will not be drawn twice, thus leaving the XOR of
  209.     ** white in the color buffer.  When using an RGB color buffer, use
  210.     ** the blend function to approximate the effects of the XOR.
  211.     */
  212.     glEnable(GL_LOGIC_OP);
  213.     glEnable(GL_BLEND);
  214.     glLogicOp(GL_XOR);
  215.     glBlendFunc(GL_ONE, GL_ONE);
  216.     SETCOLOR(MAGENTA);
  217.     /* this line is vertical */
  218.     glBegin(GL_LINE_LOOP);
  219.     glVertex2f(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(-boxH/8));
  220.     glVertex2f(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8));
  221.     glEnd();
  222.     /* this line is horizontal */
  223.     glBegin(GL_LINE_LOOP);
  224.     glVertex2f(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8+5));
  225.     glVertex2f(PIXEL_CENTER(boxW/8), PIXEL_CENTER(boxH/8+5));
  226.     glEnd();
  227.     glDisable(GL_LOGIC_OP);
  228.     glDisable(GL_BLEND);
  229.  
  230.     /*
  231.     ** Draw a point at the center of the area so that we can count pixels
  232.     ** if needed.
  233.     */
  234.     SETCOLOR(GREEN);
  235.     glBegin(GL_POINTS);
  236.     glVertex2i(0, 0);
  237.     glEnd();
  238.  
  239.     /*
  240.     ** Draw a single vertex line to make sure nothing bad happens
  241.     */
  242.     glBegin(GL_LINE_LOOP);
  243.     glVertex2i(0, 0);
  244.     glEnd();
  245. }
  246.  
  247. #define OPENGL_WIDTH    48
  248. #define OPENGL_HEIGHT    13
  249. static GLubyte OpenGL_bits[] = {
  250.    0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
  251.    0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01,
  252.    0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01, 
  253.    0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
  254.    0x3e, 0x8f, 0xb7, 0xf9, 0xfc, 0x01, 
  255.    0x63, 0xdb, 0xb0, 0x8d, 0x0d, 0x00,
  256.    0x63, 0xdb, 0xb7, 0x8d, 0x0d, 0x00, 
  257.    0x63, 0xdb, 0xb6, 0x8d, 0x0d, 0x00,
  258.    0x63, 0x8f, 0xf3, 0xcc, 0x0d, 0x00, 
  259.    0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0a,
  260.    0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0e, 
  261.    0x63, 0x00, 0x00, 0x8c, 0xed, 0x0e,
  262.    0x3e, 0x00, 0x00, 0xf8, 0x0c, 0x00, 
  263. };
  264.  
  265. static void Bitmap(void)
  266. {
  267.     static const long xOrigin = 0;
  268.     static const long yOrigin = 3;
  269.  
  270.     /*
  271.     ** Draw some lines showing the left and bottom edges of the bitmap.
  272.     ** The red line is the vertical left edge of the bitmap.  The blue
  273.     ** line is the horizontal bottom edge of the bitmap.  The yellow line
  274.     ** is the horizontal base line of the bitmap.  The green lines mark
  275.     ** where the rasterpos will translate to. Take into account the x
  276.     ** origin.
  277.     */
  278.     glBegin(GL_LINES);
  279.     SETCOLOR(GREEN);
  280.     glVertex2i(-boxW/2, 0);
  281.     glVertex2i(boxW/2, 0);
  282.     glVertex2i(0, -boxH/2);
  283.     glVertex2i(0, boxH/2);
  284.     SETCOLOR(RED);
  285.     glVertex2i(-xOrigin, -yOrigin);
  286.     glVertex2i(-xOrigin, -yOrigin+OPENGL_HEIGHT);
  287.     SETCOLOR(BLUE);
  288.     glVertex2i(-xOrigin, -yOrigin);
  289.     glVertex2i(-xOrigin+OPENGL_WIDTH, -yOrigin);
  290.     glEnd();
  291.  
  292.     SETCOLOR(GREEN);
  293.  
  294.     glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE);
  295.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  296.  
  297.     glRasterPos2i(0, 0);
  298.     glBitmap(OPENGL_WIDTH, OPENGL_HEIGHT, xOrigin, yOrigin, 0.0, 0.0, 
  299.         OpenGL_bits);
  300. }
  301.  
  302. static void Triangles(void)
  303. {
  304.     glBegin(GL_TRIANGLES);
  305.     SETCOLOR(GREEN);
  306.     glVertex2i(-boxW/4, -boxH/4);
  307.     SETCOLOR(RED);
  308.     glVertex2i(-boxW/8, -boxH/16);
  309.     SETCOLOR(BLUE);
  310.     glVertex2i(boxW/8, -boxH/16);
  311.  
  312.     SETCOLOR(GREEN);
  313.     glVertex2i(-boxW/4, boxH/4);
  314.     SETCOLOR(RED);
  315.     glVertex2i(-boxW/8, boxH/16);
  316.     SETCOLOR(BLUE);
  317.     glVertex2i(boxW/8, boxH/16);
  318.     glEnd();
  319.  
  320.     /*
  321.     ** Generate a 2 vertex triangle that should draw nothing
  322.     */
  323.     glBegin(GL_TRIANGLES);
  324.     glVertex2i(0, 0);
  325.     glVertex2i(-100, 100);
  326.     glEnd();
  327. }
  328.  
  329. static void TriangleStrip(void)
  330. {
  331.     glBegin(GL_TRIANGLE_STRIP);
  332.     SETCOLOR(GREEN);
  333.     glVertex2i(-boxW/4, -boxH/4);
  334.     SETCOLOR(RED);
  335.     glVertex2i(-boxW/4, boxH/4);
  336.     SETCOLOR(BLUE);
  337.     glVertex2i(0, -boxH/4);
  338.     SETCOLOR(WHITE);
  339.     glVertex2i(0, boxH/4);
  340.     SETCOLOR(CYAN);
  341.     glVertex2i(boxW/4, -boxH/4);
  342.     SETCOLOR(YELLOW);
  343.     glVertex2i(boxW/4, boxH/4);
  344.     glEnd();
  345.  
  346.     /*
  347.     ** Generate a 2 vertex triangle strip that should draw nothing
  348.     */
  349.     glBegin(GL_TRIANGLE_STRIP);
  350.     glVertex2i(0, 0);
  351.     glVertex2i(-100, 100);
  352.     glEnd();
  353. }
  354.  
  355. static void TriangleFan(void)
  356. {
  357.     long x0, x1, x2, x3;
  358.     long y0, y1, y2, y3;
  359.     long vx[8][2];
  360.     long i;
  361.  
  362.     /*
  363.     ** Construct an 8 sided convex polygon that is almost an octahedron
  364.     */
  365.     y0 = -boxH/4;
  366.     y1 = y0 + boxH/2/3;
  367.     y2 = y1 + boxH/2/3;
  368.     y3 = boxH/4;
  369.     x0 = -boxW/4;
  370.     x1 = x0 + boxW/2/3;
  371.     x2 = x1 + boxW/2/3;
  372.     x3 = boxW/4;
  373.  
  374.     vx[0][0] = x0; vx[0][1] = y1;
  375.     vx[1][0] = x0; vx[1][1] = y2;
  376.     vx[2][0] = x1; vx[2][1] = y3;
  377.     vx[3][0] = x2; vx[3][1] = y3;
  378.     vx[4][0] = x3; vx[4][1] = y2;
  379.     vx[5][0] = x3; vx[5][1] = y1;
  380.     vx[6][0] = x2; vx[6][1] = y0;
  381.     vx[7][0] = x1; vx[7][1] = y0;
  382.  
  383.     /*
  384.     ** Draw the polygon, shaded.  This will draw the same shape that the
  385.     ** polygon test draws, except that when flat shaded it should draw
  386.     ** entirely white.  When smooth shaded it will shade differently
  387.     ** than the polygon test.
  388.     */
  389.     glBegin(GL_TRIANGLE_FAN);
  390.     SETCOLOR(WHITE);
  391.     glVertex2i(0, 0);
  392.     for (i = 0; i < 8; i++) {
  393.         SETCOLOR(7-i);
  394.         glVertex2iv((const GLint *)vx[i]);
  395.     }
  396.     glEnd();
  397.  
  398.     /*
  399.     ** Generate a 2 vertex triangle fan that should draw nothing
  400.     */
  401.     glBegin(GL_TRIANGLE_FAN);
  402.     glVertex2i(0, 0);
  403.     glVertex2i(-100, 100);
  404.     glEnd();
  405. }
  406.  
  407. static void Rect(void)
  408. {
  409.     SETCOLOR(GREEN);
  410.     glRecti(-boxW/4, -boxH/4, boxW/4, boxH/4);
  411. }
  412.  
  413. static void Polygon(void)
  414. {
  415.     long x0, x1, x2, x3;
  416.     long y0, y1, y2, y3;
  417.     long vx[8][2];
  418.     long i;
  419.  
  420.     /*
  421.     ** Construct an 8 sided convex polygon that is almost an octahedron
  422.     */
  423.     y0 = -boxH/4;
  424.     y1 = y0 + boxH/2/3;
  425.     y2 = y1 + boxH/2/3;
  426.     y3 = boxH/4;
  427.     x0 = -boxW/4;
  428.     x1 = x0 + boxW/2/3;
  429.     x2 = x1 + boxW/2/3;
  430.     x3 = boxW/4;
  431.  
  432.     vx[0][0] = x0; vx[0][1] = y1;
  433.     vx[1][0] = x0; vx[1][1] = y2;
  434.     vx[2][0] = x1; vx[2][1] = y3;
  435.     vx[3][0] = x2; vx[3][1] = y3;
  436.     vx[4][0] = x3; vx[4][1] = y2;
  437.     vx[5][0] = x3; vx[5][1] = y1;
  438.     vx[6][0] = x2; vx[6][1] = y0;
  439.     vx[7][0] = x1; vx[7][1] = y0;
  440.  
  441.     /*
  442.     ** Draw the polygon, shaded.
  443.     */
  444.     glBegin(GL_POLYGON);
  445.     for (i = 0; i < 8; i++) {
  446.         SETCOLOR(7-i);
  447.         glVertex2iv((const GLint *)vx[i]);
  448.     }
  449.     glEnd();
  450.  
  451.     /*
  452.     ** Generate a 2 vertex polygon that should draw nothing
  453.     */
  454.     glBegin(GL_POLYGON);
  455.     glVertex2i(0, 0);
  456.     glVertex2i(100, 100);
  457.     glEnd();
  458. }
  459.  
  460. static void Quads(void)
  461. {
  462.     glBegin(GL_QUADS);
  463.     SETCOLOR(GREEN);
  464.     glVertex2i(-boxW/4, -boxH/4);
  465.     SETCOLOR(RED);
  466.     glVertex2i(-boxW/8, -boxH/16);
  467.     SETCOLOR(BLUE);
  468.     glVertex2i(boxW/8, -boxH/16);
  469.     SETCOLOR(WHITE);
  470.     glVertex2i(boxW/4, -boxH/4);
  471.  
  472.     SETCOLOR(GREEN);
  473.     glVertex2i(-boxW/4, boxH/4);
  474.     SETCOLOR(RED);
  475.     glVertex2i(-boxW/8, boxH/16);
  476.     SETCOLOR(BLUE);
  477.     glVertex2i(boxW/8, boxH/16);
  478.     SETCOLOR(WHITE);
  479.     glVertex2i(boxW/4, boxH/4);
  480.     glEnd();
  481.  
  482.     /*
  483.     ** Generate a 3 vertex quad that should draw nothing
  484.     */
  485.     glBegin(GL_QUADS);
  486.     glVertex2i(0, 0);
  487.     glVertex2i(100, 100);
  488.     glVertex2i(-100, 100);
  489.     glEnd();
  490. }
  491.  
  492. static void QuadStrip(void)
  493. {
  494.     glBegin(GL_QUAD_STRIP);
  495.     SETCOLOR(GREEN);
  496.     glVertex2i(-boxW/4, -boxH/4);
  497.     SETCOLOR(RED);
  498.     glVertex2i(-boxW/4, boxH/4);
  499.     SETCOLOR(BLUE);
  500.     glVertex2i(0, -boxH/4);
  501.     SETCOLOR(WHITE);
  502.     glVertex2i(0, boxH/4);
  503.     SETCOLOR(CYAN);
  504.     glVertex2i(boxW/4, -boxH/4);
  505.     SETCOLOR(YELLOW);
  506.     glVertex2i(boxW/4, boxH/4);
  507.     glEnd();
  508.  
  509.     /*
  510.     ** Generate a 3 vertex quad strip that should draw nothing
  511.     */
  512.     glBegin(GL_QUAD_STRIP);
  513.     glVertex2i(0, 0);
  514.     glVertex2i(100, 100);
  515.     glVertex2i(-100, 100);
  516.     glEnd();
  517. }
  518.  
  519. static void RotateColorMask(void)
  520. {
  521.     static long rotation=0;
  522.     
  523.     rotation = (rotation + 1) & 0x3;
  524.     switch (rotation) {
  525.       case 0:
  526.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  527.     glIndexMask( 0xff );
  528.     break;
  529.       case 1:
  530.     /* mask off red */
  531.     glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
  532.     glIndexMask( 0xfe );
  533.     break;
  534.       case 2:
  535.     /* mask off green */
  536.     glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
  537.     glIndexMask( 0xfd );
  538.     break;
  539.       case 3:
  540.     /* mask off blue */
  541.     glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
  542.     glIndexMask( 0xfb );
  543.     break;
  544.     }
  545. }
  546.  
  547. static void DoTests(void)
  548. {
  549.     glClearColor(0.0, 0.0, 0.0, 0.0);
  550.  
  551.     Viewport(0, 0); Point();
  552.     Viewport(0, 1); Lines();
  553.     Viewport(0, 2); LineStrip();
  554.     Viewport(0, 3); LineLoop();
  555.  
  556.     Viewport(1, 0); Bitmap();
  557.     Viewport(1, 1); TriangleFan();
  558.     Viewport(1, 2); Triangles();
  559.     Viewport(1, 3); TriangleStrip();
  560.  
  561.     Viewport(2, 0); Rect();
  562.     Viewport(2, 1); Polygon();
  563.     Viewport(2, 2); Quads();
  564.     Viewport(2, 3); QuadStrip();
  565.  
  566.     glFlush();
  567. }
  568.  
  569. static void Usage(void)
  570. {
  571.     printf("Usage: tprim [-c]\n");
  572.     printf("   -c:  Run in color index mode\n");
  573.     exit(-1);
  574. }
  575.  
  576. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  577. {
  578.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  579.     return GL_TRUE;
  580.     }
  581.     return GL_FALSE;
  582. }
  583.  
  584. int main(int argc, char** argv)
  585. {
  586.     XVisualInfo *vi;
  587.     Display *dpy;
  588.     Colormap cmap;
  589.     Window window;
  590.     XSetWindowAttributes swa;
  591.     GLXContext cx;
  592.     XEvent event;
  593.     GLboolean needDisplay;
  594.     XColor white;
  595.     char *geometry = NULL;
  596.     XSizeHints sizehints;
  597.     int i;
  598.     long menu, smenu, pmenu;
  599.  
  600.     rgb = 1;
  601.     for (i = 1; i < argc; i++) {
  602.     if (!strcmp(argv[i], "-geometry")) {
  603.         i++;
  604.         geometry = argv[i];
  605.     } else if (argv[i][0] == '-') {
  606.             switch (argv[i][1]) {
  607.               case 'c':
  608.                 rgb = GL_FALSE;
  609.                 break;
  610.               default:
  611.                 Usage();
  612.             }
  613.         } else {
  614.             Usage();
  615.         }
  616.     }
  617.  
  618.     dpy = XOpenDisplay(0);
  619.     if (!dpy) {
  620.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  621.     return -1;
  622.     }
  623.  
  624.     vi = glXChooseVisual(dpy, DefaultScreen(dpy),
  625.              rgb ? RGB_attributes : CI_attributes);
  626.     if (!vi) {
  627.     fprintf(stderr, "No singlebuffered rgba visual on \"%s\"\n",
  628.         getenv("DISPLAY"));
  629.     return -1;
  630.     }
  631.  
  632.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  633.                AllocNone);
  634.     white.red = ~0;
  635.     white.green = ~0;
  636.     white.blue = ~0;
  637.     XAllocColor(dpy, cmap, &white);
  638.  
  639.     sizehints.flags = PPosition | PSize;
  640.     sizehints.width = W;
  641.     sizehints.height = H;
  642.     sizehints.x = 10;
  643.     sizehints.y = 10;
  644.     if(geometry) {
  645.     int flags, x, y, width, height;
  646.  
  647.     flags = XParseGeometry(geometry, &x, &y,
  648.                    (unsigned int *)&width,
  649.                    (unsigned int *)&height);
  650.         if(WidthValue & flags) {
  651.         sizehints.flags |= USSize;
  652.         sizehints.width = width;
  653.         W = width;
  654.     }
  655.     if(HeightValue & flags) {
  656.         sizehints.flags |= USSize;
  657.         sizehints.height = height;
  658.         H = height;
  659.     }
  660.     if(XValue & flags) {
  661.         if(XNegative & flags)
  662.         x = DisplayWidth(dpy, DefaultScreen(dpy)) + x 
  663.             - sizehints.width;
  664.             sizehints.flags |= USPosition;
  665.         sizehints.x = x;
  666.     }
  667.     if(YValue & flags) {
  668.         if(YNegative & flags)
  669.         y = DisplayHeight(dpy, DefaultScreen(dpy)) + y 
  670.             - sizehints.height;
  671.             sizehints.flags |= USPosition;
  672.         sizehints.y = y;
  673.     }
  674.     }
  675.     swa.border_pixel = 0;
  676.     swa.background_pixel = white.pixel;
  677.     swa.colormap = cmap;
  678.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  679.     | KeyReleaseMask | ButtonPressMask;
  680.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  681.                            sizehints.x, sizehints.y,
  682.                sizehints.width, sizehints.height,
  683.                0, vi->depth, InputOutput, vi->visual,
  684.                CWBackPixel|CWBorderPixel|CWColormap|CWEventMask,
  685.                &swa);
  686.     XSetStandardProperties(dpy, window, rgb ? "tprim RGB" : "tprim CI", "tprim",
  687.                            None, argv, argc, &sizehints);
  688.     XSetWMColormapWindows(dpy, window, &window, 1);
  689.     XMapWindow(dpy, window);
  690.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  691.  
  692.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  693.     if (!glXMakeCurrent(dpy, window, cx)) {
  694.     fprintf(stderr, "Can't make window current to context\n");
  695.     return -1;
  696.     }
  697.     smenu = defpup(dpy, DefaultScreen(dpy), "GL_FLAT %x1|GL_SMOOTH %x2");
  698.     pmenu = defpup(dpy, DefaultScreen(dpy), "GL_FILL %x3|GL_LINE %x4|GL_POINT %x5");
  699.     menu = defpup(dpy, DefaultScreen(dpy), "glShadeModel %m|glPolygonMode %m|rotate color mask %x6%l|quit %x7", smenu, pmenu);
  700.  
  701.     needDisplay = GL_TRUE;
  702.     for (;;) {
  703.     do {
  704.         XNextEvent(dpy, &event);
  705.         switch (event.type) {
  706.           case Expose:
  707.         needDisplay = GL_TRUE;
  708.         break;
  709.           case ConfigureNotify:
  710.         W = event.xconfigure.width;
  711.         H = event.xconfigure.height;
  712.         needDisplay = GL_TRUE;
  713.         break;
  714.           case KeyPress:
  715.         {
  716.             char buf[100];
  717.             int rv;
  718.             KeySym ks;
  719.  
  720.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  721.             switch (ks) {
  722.               case XK_F:
  723.               case XK_f:
  724.             glShadeModel(GL_FLAT);
  725.             needDisplay = GL_TRUE;
  726.             break;
  727.               case XK_S:
  728.               case XK_s:
  729.             glShadeModel(GL_SMOOTH);
  730.             needDisplay = GL_TRUE;
  731.             break;
  732.               case XK_P:
  733.               case XK_p:
  734.             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  735.             needDisplay = GL_TRUE;
  736.             break;
  737.               case XK_L:
  738.               case XK_l:
  739.             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  740.             needDisplay = GL_TRUE;
  741.             break;
  742.               case XK_C:
  743.               case XK_c:
  744.             RotateColorMask();
  745.             needDisplay = GL_TRUE;
  746.             break;
  747.               case XK_Escape:
  748.             return 0;
  749.             }
  750.         }
  751.         break;
  752.           case ButtonPress:
  753.         switch(dopup(menu)) {
  754.         case 1:
  755.             glShadeModel(GL_FLAT);
  756.             needDisplay = GL_TRUE;
  757.             break;
  758.         case 2:
  759.             glShadeModel(GL_SMOOTH);
  760.             needDisplay = GL_TRUE;
  761.             break;
  762.         case 3:
  763.             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  764.             needDisplay = GL_TRUE;
  765.             break;
  766.         case 4:
  767.             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  768.             needDisplay = GL_TRUE;
  769.             break;
  770.         case 5:
  771.             glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  772.             needDisplay = GL_TRUE;
  773.             break;
  774.         case 6:
  775.             RotateColorMask();
  776.             needDisplay = GL_TRUE;
  777.             break;
  778.         case 7:
  779.             exit(0);
  780.         case -1:
  781.             break;
  782.         }
  783.         }
  784.     } while (XPending(dpy) != 0);
  785.  
  786.     if (needDisplay) {
  787.         needDisplay = GL_FALSE;
  788.         DoTests();
  789.     }
  790.     }
  791. }
  792.